# -*- coding: utf-8 -*-
"""
FastAPI主应用

提供CRM系统的Web API服务，包括：
- RESTful API接口
- 用户认证和权限管理
- 自动API文档生成
- 统一错误处理
- 跨域资源共享
"""

from fastapi import FastAPI, Request, Response
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.exceptions import RequestValidationError, HTTPException
from fastapi.responses import JSONResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
from contextlib import asynccontextmanager
import logging
import time
from typing import Dict, Any
import os

from .middleware.logging_middleware import LoggingMiddleware
from .middleware.security_middleware import SecurityMiddleware
from .middleware.request_body_cache_middleware import RequestBodyCacheMiddleware
from .core.config import get_settings
from .core.exceptions import CRMException, ErrorCode
from .api.v1 import api_router
from .core.database import init_database, close_database

logger = logging.getLogger(__name__)
settings = get_settings()


@asynccontextmanager
async def lifespan(app: FastAPI):
    """应用生命周期管理"""
    # 启动时初始化
    logger.info("正在启动CRM Web应用...")

    # 初始化数据库
    try:
        await init_database()
        logger.info("数据库初始化完成")
    except Exception as e:
        logger.error(f"数据库初始化失败: {e}")
        raise

    logger.info("CRM Web应用启动完成")

    yield

    # 关闭时清理
    logger.info("正在关闭CRM Web应用...")

    try:
        await close_database()
        logger.info("数据库连接已关闭")
    except Exception as e:
        logger.error(f"数据库关闭失败: {e}")

    logger.info("CRM Web应用已关闭")


def create_app() -> FastAPI:
    """创建FastAPI应用实例"""

    app = FastAPI(
        title="CRM旅游管理系统",
        description="专为中老年旅游客户设计的客户关系管理系统",
        version="2.0.0",
        docs_url=None,  # 禁用默认docs，使用自定义
        redoc_url="/redoc" if settings.DEBUG else None,
        openapi_url="/openapi.json" if settings.DEBUG else None,
        lifespan=lifespan,
        swagger_ui_parameters={
            "defaultModelsExpandDepth": -1,
            "displayRequestDuration": True,
            "filter": True,
            "showExtensions": True,
            "showCommonExtensions": True,
            "tryItOutEnabled": True
        }
    )

    # 配置中间件
    setup_middleware(app)

    # 配置异常处理器
    setup_exception_handlers(app)

    # 注册路由
    app.include_router(api_router, prefix="/api/v1")

    # 配置静态文件服务
    static_dir = os.path.join(os.path.dirname(__file__), "..", "static")
    if os.path.exists(static_dir):
        app.mount("/static", StaticFiles(directory=static_dir), name="static")

    # 自定义Swagger UI路由
    if settings.DEBUG:
        @app.get("/docs", response_class=HTMLResponse)
        async def custom_swagger_ui_html():
            """自定义Swagger UI HTML - 使用可靠的CDN"""
            html_content = """
            <!DOCTYPE html>
            <html>
            <head>
                <title>CRM旅游管理系统 - API文档</title>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <link rel="stylesheet" type="text/css" href="/static/swagger-ui.css" />
                <style>
                    html { 
                        box-sizing: border-box; 
                        overflow: -moz-scrollbars-vertical; 
                        overflow-y: scroll; 
                    }
                    *, *:before, *:after { box-sizing: inherit; }
                    body { 
                        margin: 0; 
                        background: #fafafa; 
                        font-family: "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", Arial, sans-serif; 
                    }
                    .swagger-ui .topbar { 
                        background-color: #1976d2; 
                        padding: 10px 0;
                    }
                    .swagger-ui .topbar .link { 
                        color: #ffffff; 
                        font-weight: bold;
                    }
                    .swagger-ui .info .title { 
                        color: #1976d2; 
                        font-size: 36px;
                        margin-bottom: 10px;
                    }
                    .swagger-ui .btn.authorize { 
                        background-color: #4caf50; 
                        border-color: #4caf50; 
                        color: white;
                    }
                    .swagger-ui .btn.authorize:hover { 
                        background-color: #45a049; 
                        border-color: #45a049;
                    }
                    .swagger-ui .opblock.opblock-post { 
                        border-color: #4caf50; 
                        background: rgba(76, 175, 80, 0.1); 
                    }
                    .swagger-ui .opblock.opblock-get { 
                        border-color: #2196f3; 
                        background: rgba(33, 150, 243, 0.1); 
                    }
                    .swagger-ui .opblock.opblock-put { 
                        border-color: #ff9800; 
                        background: rgba(255, 152, 0, 0.1); 
                    }
                    .swagger-ui .opblock.opblock-delete { 
                        border-color: #f44336; 
                        background: rgba(244, 67, 54, 0.1); 
                    }
                </style>
            </head>
            <body>
                <div id="swagger-ui">
                    <div style="padding: 20px; text-align: center;">
                        <h3>正在加载API文档...</h3>
                        <p>请稍候...</p>
                    </div>
                </div>
                
                <script src="/static/swagger-ui-bundle.js"></script>
                <script>
                window.onload = function() {
                    console.log('页面加载完成，初始化Swagger UI...');
                    
                    // 检查SwaggerUIBundle是否加载
                    if (typeof SwaggerUIBundle === 'undefined') {
                        console.error('SwaggerUIBundle未定义，尝试重新加载...');
                        setTimeout(function() {
                            if (typeof SwaggerUIBundle === 'undefined') {
                                document.getElementById('swagger-ui').innerHTML = 
                                    '<div style="padding: 20px; text-align: center; color: red;">' +
                                    '<h3>加载失败</h3>' +
                                    '<p>Swagger UI资源加载失败，可能是网络问题。</p>' +
                                    '<p><a href="/openapi.json" target="_blank">点击查看原始API规范</a></p>' +
                                    '<button onclick="location.reload()">重新加载</button>' +
                                    '</div>';
                            } else {
                                initSwagger();
                            }
                        }, 2000);
                        return;
                    }
                    
                    initSwagger();
                };
                
                function initSwagger() {
                    try {
                        console.log('开始初始化Swagger UI...');
                        const ui = SwaggerUIBundle({
                            url: '/openapi.json',
                            dom_id: '#swagger-ui',
                            deepLinking: true,
                            presets: [
                                SwaggerUIBundle.presets.apis,
                                SwaggerUIBundle.presets.standalone
                            ],
                            plugins: [
                                SwaggerUIBundle.plugins.DownloadUrl
                            ],
                            // 移除layout配置，使用默认layout
                            defaultModelsExpandDepth: -1,
                            displayRequestDuration: true,
                            filter: true,
                            showExtensions: true,
                            showCommonExtensions: true,
                            tryItOutEnabled: true,
                            validatorUrl: null,
                            docExpansion: "list",
                            tagsSorter: "alpha",
                            operationsSorter: "alpha",
                            onComplete: function() {
                                console.log('Swagger UI 加载完成！');
                            },
                            onFailure: function(err) {
                                console.error('Swagger UI 加载失败:', err);
                                document.getElementById('swagger-ui').innerHTML = 
                                    '<div style="padding: 20px; text-align: center; color: red;">' +
                                    '<h3>初始化失败</h3>' +
                                    '<p>错误: ' + err + '</p>' +
                                    '<p><a href="/openapi.json" target="_blank">点击查看原始API规范</a></p>' +
                                    '</div>';
                            }
                        });
                        
                        window.ui = ui;
                        
                    } catch (error) {
                        console.error('Swagger UI 初始化异常:', error);
                        document.getElementById('swagger-ui').innerHTML = 
                            '<div style="padding: 20px; text-align: center; color: red;">' +
                            '<h3>初始化异常</h3>' +
                            '<p>错误: ' + error.message + '</p>' +
                            '<p><a href="/openapi.json" target="_blank">点击查看原始API规范</a></p>' +
                            '<button onclick="location.reload()">重新加载</button>' +
                            '</div>';
                    }
                }
                </script>
            </body>
            </html>
            """
            return html_content

    # 健康检查端点
    @app.get("/health")
    async def health_check() -> Dict[str, Any]:
        """健康检查"""
        return {
            "status": "healthy",
            "timestamp": time.time(),
            "version": "2.0.0"
        }

    # Chrome DevTools端点（避免404错误）
    @app.get("/.well-known/appspecific/com.chrome.devtools.json")
    async def chrome_devtools():
        """Chrome开发者工具配置（可选）"""
        return {"version": "1.0", "type": "web-application"}

    return app


def setup_middleware(app: FastAPI) -> None:
    """配置中间件"""

    # 安全中间件 - 临时完全禁用调试500错误
    # app.add_middleware(SecurityMiddleware, enable_request_validation=False)

    # 日志中间件 - 启用但不记录请求体
    app.add_middleware(LoggingMiddleware)

    # CORS中间件
    cors_origins = ["*"]  # 开发环境允许所有源
    if settings.BACKEND_CORS_ORIGINS:
        cors_origins = [str(origin) for origin in settings.BACKEND_CORS_ORIGINS]

    app.add_middleware(
        CORSMiddleware,
        allow_origins=cors_origins,
        allow_credentials=True,
        allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
        allow_headers=[
            "Accept",
            "Accept-Language",
            "Content-Language",
            "Content-Type",
            "Authorization",
            "X-Requested-With",
            "Origin",
            "Access-Control-Request-Method",
            "Access-Control-Request-Headers",
        ],
        expose_headers=["*"],
    )

    # 可信主机中间件
    if settings.ALLOWED_HOSTS:
        app.add_middleware(
            TrustedHostMiddleware,
            allowed_hosts=settings.ALLOWED_HOSTS
        )
    
    # 请求体缓存中间件 - 暂时禁用，直接避免请求体读取问题
    # app.add_middleware(RequestBodyCacheMiddleware)


def setup_exception_handlers(app: FastAPI) -> None:
    """配置异常处理器"""

    @app.exception_handler(CRMException)
    async def crm_exception_handler(request: Request, exc: CRMException):
        """CRM业务异常处理器"""
        logger.warning(f"业务异常: {exc.message}", extra={
            "error_code": exc.error_code,
            "request_url": str(request.url),
            "request_method": request.method
        })

        return JSONResponse(
            status_code=exc.status_code,
            content={
                "error": True,
                "error_code": exc.error_code,
                "message": exc.message,
                "details": exc.details,
                "timestamp": time.time()
            }
        )

    @app.exception_handler(HTTPException)
    async def http_exception_handler(request: Request, exc: HTTPException):
        """HTTP异常处理器"""
        logger.warning(f"HTTP异常: {exc.detail}", extra={
            "status_code": exc.status_code,
            "request_url": str(request.url),
            "request_method": request.method
        })

        return JSONResponse(
            status_code=exc.status_code,
            content={
                "error": True,
                "error_code": f"HTTP_{exc.status_code}",
                "message": exc.detail,
                "timestamp": time.time()
            }
        )

    @app.exception_handler(RequestValidationError)
    async def validation_exception_handler(request: Request, exc: RequestValidationError):
        """请求验证异常处理器"""
        logger.warning(f"请求验证失败: {exc.errors()}", extra={
            "request_url": str(request.url),
            "request_method": request.method
        })

        return JSONResponse(
            status_code=422,
            content={
                "error": True,
                "error_code": ErrorCode.VALIDATION_ERROR,
                "message": "请求参数验证失败",
                "details": exc.errors(),
                "timestamp": time.time()
            }
        )

    @app.exception_handler(Exception)
    async def general_exception_handler(request: Request, exc: Exception):
        """通用异常处理器"""
        logger.error(f"未处理的异常: {str(exc)}", extra={
            "request_url": str(request.url),
            "request_method": request.method,
            "exception_type": type(exc).__name__
        }, exc_info=True)

        return JSONResponse(
            status_code=500,
            content={
                "error": True,
                "error_code": ErrorCode.INTERNAL_ERROR,
                "message": "服务器内部错误" if not settings.DEBUG else str(exc),
                "timestamp": time.time()
            }
        )


# 创建应用实例
app = create_app()

if __name__ == "__main__":
    import uvicorn

    uvicorn.run(
        "src.app:app",
        host=settings.HOST,
        port=settings.PORT,
        reload=settings.DEBUG,
        log_level="info" if not settings.DEBUG else "debug"
    )
